package com.yanqu.road;

import com.yanqu.road.connect.AgentServerLinkControl;
import com.yanqu.road.player.PlayerControl;
import com.yanqu.road.server.TempMgr;
import com.yanqu.road.server.TempServer;
import com.yanqu.road.server.manger.ServerListMgr;
import com.yanqu.road.thread.ThreadPoolHelper;
import com.yanqu.road.timer.GeneralAgentTimerMgr;
import com.yanqu.road.utils.ServerType;
import com.yanqu.road.utils.config.Config;
import com.yanqu.road.utils.executor.ScheduledThreadPoolHelper;
import com.yanqu.road.utils.executor.GeneralThreadFactory;
import com.yanqu.road.utils.monitor.MonitorHelper;
import com.yanqu.road.utils.net.ServerNetConfig;
import com.yanqu.road.utils.net.ServerNetConfigHelper;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ThreadPoolExecutor;

public final class AgentServer extends TempServer {

    private static Logger logger = LogManager.getLogger(AgentServer.class.getName());

    private AgentServerNettyService sslServer;

    private static AgentServer agentServer;

    private boolean isStop;

    private static ExecutorService serverCommandExecutor = null;

    private AgentServer() {

    }

    public boolean isStop() {
        return isStop;
    }

    public void setStop(boolean stop) {
        this.isStop = stop;
    }

    public static ExecutorService getServerCommandExecutor() {
        return serverCommandExecutor;
    }

    public static AgentServer getInstance() {
        if (null == agentServer) {
            agentServer = new AgentServer();
        }
        return agentServer;
    }

    @Override
    public boolean start() {
      /*  if (!super.start()) {
            return false;
        }*/
        initTempMgrList();
        //设置消息处理线程数量
        serverCommandExecutor = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors() * 3,
                new GeneralThreadFactory("agentServer-cmd"));
        timerScheduledExecutorService = ScheduledThreadPoolHelper.createGameScheduledThreadPoolExecutor(5, "timer-agentServer");
        MonitorHelper.monitorPool("agentServer-cmd", (ThreadPoolExecutor) serverCommandExecutor);
        if (!initGameModule(PlayerControl.init(), "player mgr")) {
            return false;
        }

        if (!initGameModule(AgentServerLinkControl.init(0), "server connect set")) {
            return false;
        }

        if (!initGameModule(ThreadPoolHelper.init(), "load command thread pool")) {
            return false;
        }

        if (!initGameModule(startNetty(), "load netty")) {
            return false;
        }

   /*     Runtime.getRuntime().addShutdownHook(new Thread(() -> {
            logger.info("GameServer kill 关闭服务器");
            AgentServer.getInstance().newStop();

        }));*/

        try {
            Thread.sleep(3000);
            if (!sslServer.isPortOpen()) {
                logger.error("netty port open error");
                return false;
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
            return false;
        }

        return true;
    }

    @Override
    public boolean stop() {
        try {
            sslServer.stop();
            PlayerControl.stop();
            super.stop();
        } catch (Exception e) {
            logger.error("AgentServer stop error", e);
            return false;
        }

        return true;
    }

    public boolean newStop() {
        try {
           /* int minutes = ServerBussiness.getCloseServerCountdownMinutes();
            while (minutes > 0) {
                try {
                    logger.info("倒计时 {} 分钟", minutes);
                    ServerProto.ServerStopNoticeMsg.Builder msg = ServerProto.ServerStopNoticeMsg.newBuilder();
                    msg.setMinutes(minutes);
                    YanQuMessage stopMsg = YanQuMessageUtils.buildMessageByte(Protocol.U_SERVER_STOP_NOTICE, msg.build().toByteArray());
                    Map<Long, Player> playerMap = new HashMap<>(PlayerControl.getOnlinePlayerMap());
                    for (Map.Entry<Long, Player> dataEntry : playerMap.entrySet()) {
                        stopMsg.setPlayerId(dataEntry.getKey());
                        AgentServerLinkControl.routeClient(stopMsg);
                    }

                    // 等待60秒
                    Thread.sleep(10000);

                } catch (Exception ex) {
                    ex.printStackTrace();
                } finally {
                    minutes--;
                }
            }*/

            sslServer.stop();
            PlayerControl.stop();
            TempServer.deleteFile("./agentServer.pid");
            logger.info("------------");
            logger.info("------------");
            logger.info("------------");
            logger.info("------------");
        } catch (Exception e) {
            logger.error("AgentServer stop error", e);
            return false;
        }

        return true;
    }


    protected boolean startNetty() {
        ServerNetConfig netXml = ServerNetConfigHelper.getServerNetConfig(sType, 0);

        sslServer = new AgentServerNettyService(sid, netXml.getPort());
        try {
            timerScheduledExecutorService.execute(() -> {
                try {
                    sslServer.start(true);
                } catch (Exception e) {
                    logger.error("start netty error", e);
                }
            });
        } catch (Exception e) {
            logger.error("start netty error", e);
            return false;
        }

        return true;
    }

    public static void main(String[] args) {
        long time = System.currentTimeMillis();
        if (args.length <= 0) {
            System.err.println("check set config path");
            return;
        }
        Config.ParseArgs(args);
        cfgPath = args[0];
        AgentServer agentServer = AgentServer.getInstance();
        agentServer.setServerType(Integer.valueOf(args[1]));
        if (!agentServer.start()) {
            System.err.println("AgentServer start fail!");
            System.exit(1);
            return;
        }
        GeneralAgentTimerMgr.initGeneralTimers();


        logger.info("AgentServer start success,cost time:" + (System.currentTimeMillis() - time));
        logger.info("notify process start success!");  //日志启动成功标识

        for (int i = 0; i < 100; i++) {
            logger.info("--------------");
        }
        logger.info("notify process start success!");  //日志启动成功标识
        TempServer.tempServerLogger.info("notify process start success!");
    }

    public static void agentStart(String configFile) {
        long time = System.currentTimeMillis();

        cfgPath = configFile;
        AgentServer agentServer = AgentServer.getInstance();
        agentServer.setServerType(ServerType.SERVER_AGENT);
        if (!agentServer.start()) {
            System.err.println("AgentServer start fail!");
            System.exit(1);
            return;
        }
        GeneralAgentTimerMgr.initGeneralTimers();


        logger.info("AgentServer start success,cost time:" + (System.currentTimeMillis() - time));
        logger.info("notify process start success!");  //日志启动成功标识

        for (int i = 0; i < 100; i++) {
            logger.info("--------------");
        }
        logger.info("notify process start success!");  //日志启动成功标识
    }

    @Override
    public List<TempMgr> getMgrList() {
        List<TempMgr> mgrList = new ArrayList<>();
        mgrList.add(new ServerListMgr());
        return mgrList;
    }
}
